﻿/***GO-BACK-N协议，确认帧为捎带确认***/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>

#include "protocol.h"
#include "datalink.h"

#define inc(k) if(k<MAX_SEQ) k=k+1; else k=0;
#define DATA_TIMER  2000
#define ACK_TIMER 256
#define MAX_SEQ 15


typedef struct {
	unsigned char kind; /* FRAME_DATA */
	unsigned char ack;			 //ACK number
	unsigned char seq;			 //seq number
	unsigned char data[PKT_LEN]; //净荷域
	unsigned int  padding;       //存放CRC校验和
}frame;


static unsigned char frame_nr = 0, buffer[MAX_SEQ + 1][PKT_LEN], nbuffered = 0;
int packet_length[MAX_SEQ + 1];
static unsigned char frame_expected = 0, ack_expected = 0, next_frame_to_send = 0;
static int phl_ready = 0;
//frame_nr目前帧  buffer缓冲区 nbuffered目前的缓冲区
//packet_length包长度 frame_expected希望收到的帧
//ack_expected希望收到的ack next_frame_to_send下一个要发送的帧
int between(unsigned char a, unsigned char b, unsigned char c)	//判断帧有没有在当前窗口中
{
	if (((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a)))
	//a:ack_expected,b:f.ack,c:next_frame_to_send
		return 1;
	else
		return 0;
}



static void put_frame(unsigned char* frame, int len)
{
	*(unsigned int*)(frame + len) = crc32(frame, len);
	send_frame(frame, len + 4);
	phl_ready = 0;
}

static void send_data_frame(void)					//将帧传递给物理层传送，并开始计时器计时
{
	frame s;
	s.kind = FRAME_DATA;
	s.seq = next_frame_to_send;
	s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1);
	memcpy(s.data, buffer[next_frame_to_send], PKT_LEN);
	dbg_frame("Send DATA %d %d, ID %d,windows %d\n", s.seq, s.ack, *(short*)s.data, nbuffered);
	put_frame((unsigned char*)&s, 3 + PKT_LEN);
	start_timer(next_frame_to_send, DATA_TIMER);

}
#define send_marumaru_frame(FRAME_TYPE, FRAME_TYPENAME)                 \
    static void send_##FRAME_TYPE##_frame(unsigned char frame_expected) \
    {                                                                   \
        frame s;                                                 \
                                                                        \
        s.kind = FRAME_##FRAME_TYPE;                                    \
        s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1);             \
                                                                        \
        dbg_frame("Send " FRAME_TYPENAME " %d\n", s.ack);               \
                                                                        \
        put_frame((unsigned char*)&s, 2);                               \
    }

send_marumaru_frame(ACK, "ACK")

send_marumaru_frame(NAK, "NAK")



int main(int argc, char** argv)
{
	int event, arg;
	frame f;
	bool no_nak = true;

	int len = 0;
	int i;
	protocol_init(argc, argv);
	lprintf("Designed by Jiang Yanjun, build: " __DATE__"  "__TIME__"\n");

	disable_network_layer();					//开始状态，网络层禁止递交分组

	for (;;) {
		event = wait_for_event(&arg);
		switch (event) {
		case NETWORK_LAYER_READY:				//网络层有分组要发送
			get_packet(buffer[next_frame_to_send]);
			nbuffered++;
			send_data_frame();
			inc(next_frame_to_send); //next_frame_to_send++
			break;

		case PHYSICAL_LAYER_READY:				//物理层准备好了
			phl_ready = 1;
			break;

		case FRAME_RECEIVED:					//一个数据帧到达

			len = recv_frame((unsigned char*)&f, sizeof f);
			//错误的frame应该返回nak
			if (len < 5 || crc32((unsigned char*)&f, len) != 0) {
				dbg_event("**** Receiver Error, Bad CRC Checksum\n");
				if (no_nak) {
					send_NAK_frame(frame_expected);
					no_nak = true;
					stop_ack_timer();
				}
				break;
			}

			
				if (f.kind == FRAME_ACK)
					dbg_frame("Recv ACK  %d\n", f.ack);
				if (f.kind == FRAME_NAK)
					dbg_frame("Recv NAK  %d\n", f.ack);
				if (f.kind == FRAME_DATA) {
					dbg_frame("Recv DATA %d %d, ID %d\n", f.seq, f.ack, *(short*)f.data);
					if (f.seq == frame_expected) {
						put_packet(f.data, len - 7);
						no_nak = true;
						inc(frame_expected);
						start_ack_timer(ACK_TIMER);
					}
					else if (no_nak) {
						send_NAK_frame(frame_expected);
						no_nak = false;
						stop_ack_timer();
					}
				}
				//停止所有的定时器
				while (between(ack_expected, f.ack, next_frame_to_send))
				{
					nbuffered = nbuffered - 1;
					stop_timer(ack_expected);
					inc(ack_expected);
				}
				if (f.kind == FRAME_NAK) {
					stop_timer(ack_expected + 1);
					next_frame_to_send = ack_expected;
					// 重新发送预期包
					for ( i = 0; i < nbuffered; i++) {
						send_data_frame(next_frame_to_send, frame_expected, buffer[next_frame_to_send], packet_length[next_frame_to_send]);
						start_timer(next_frame_to_send, DATA_TIMER);
						stop_ack_timer();

						inc(next_frame_to_send);
					}

					phl_ready = 0;
				}
				
			break;

		case DATA_TIMEOUT:						//TIMER超时，重传发送窗口中所有帧
			dbg_event("---- DATA %d timeout\n", arg);
			next_frame_to_send = ack_expected;
			for (i = 1; i <= nbuffered; i++)
			{
				send_data_frame();
				start_timer(next_frame_to_send, DATA_TIMER);
				stop_ack_timer();
				inc(next_frame_to_send);
			}
			phl_ready = 0;
			break;
		case ACK_TIMEOUT:
			send_ACK_frame(frame_expected);
			stop_ack_timer();
			break;
		}
		
		if (nbuffered < MAX_SEQ && phl_ready)
			enable_network_layer();
		else
			disable_network_layer();
	}
		return 0;
	}



